package cn.exrick.xboot.common.utils;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class BeanConverterUtil {

    /**
     * 将一个 List 中的元素从源类型转换为目标类型
     *
     * @param sourceList 源 List
     * @param targetClass 目标类型的 Class 对象
     * @param <S> 源类型的泛型
     * @param <T> 目标类型的泛型
     * @return 转换后的目标 List
     */
    public static <S, T> List<T> convertList(List<S> sourceList, Class<T> targetClass) {
        if (sourceList == null || sourceList.isEmpty()) {
            return new ArrayList<>();
        }
        return sourceList.stream()
                .map(source -> {
                    T target;
                    try {
                        // 创建目标对象的实例
                        target = targetClass.getDeclaredConstructor().newInstance();
                        // 使用 Hutool 的 BeanUtil 复制属性
                        BeanUtil.copyProperties(source, target);
                    } catch (Exception e) {
                        throw new RuntimeException("Bean 转换失败", e);
                    }
                    return target;
                })
                .collect(Collectors.toList());
    }

    /**
     * 将单个源 Bean 转换为目标 Bean
     *
     * @param source 源 Bean
     * @param targetClass 目标类型的 Class 对象
     * @param <S> 源类型的泛型
     * @param <T> 目标类型的泛型
     * @return 转换后的目标 Bean
     */
    public static <S, T> T convertBean(S source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        try {
            // 创建目标对象的实例
            T target = targetClass.getDeclaredConstructor().newInstance();
            // 使用 Hutool 的 BeanUtil 复制属性
            BeanUtil.copyProperties(source, target);
            return target;
        } catch (Exception e) {
            throw new RuntimeException("Bean 转换失败", e);
        }
    }

    /**
     * 将 MyBatis-Plus 的 Page 对象中的 Bean 进行转换
     *
     * @param sourcePage 源 Page 对象
     * @param targetClass 目标类型的 Class 对象
     * @param <S> 源类型的泛型
     * @param <T> 目标类型的泛型
     * @return 转换后的目标 Page 对象
     */
    public static <S, T> IPage<T> convertPage(IPage<S> sourcePage, Class<T> targetClass) {
        if (sourcePage == null) {
            return null;
        }
        List<T> targetRecords = convertList(sourcePage.getRecords(), targetClass);
        Page<T> targetPage = new Page<>(sourcePage.getCurrent(), sourcePage.getSize(), sourcePage.getTotal());
        targetPage.setRecords(targetRecords);
        return targetPage;
    }
}
